package com.ccrfid.rmc6.service.map;

import com.ccrfid.rmc6.entity.asset.AssetView;
import com.ccrfid.rmc6.entity.personnel.PersonnelPrisonerEntity;
import com.ccrfid.rmc6.entity.personnel.PersonnelPrisonerView;
import com.ccrfid.rmc6.entity.personnel.PersonnelView;
import com.ccrfid.rmc6.entity.poi.PoiLocationEntity;
import com.ccrfid.rmc6.pojo.Constants;
import com.ccrfid.rmc6.pojo.dto.PersonnelSearchDto;
import com.ccrfid.rmc6.repository.asset.AssetViewRepository;
import com.ccrfid.rmc6.repository.personnel.PersonnelPrisonerRepository;
import com.ccrfid.rmc6.repository.personnel.PersonnelPrisonerViewRepository;
import com.ccrfid.rmc6.repository.personnel.PersonnelViewRepository;
import com.ccrfid.rmc6.repository.poi.PoiLocationRepository;
import com.ccrfid.rmc6.repository.search.Criterion;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.util.RegexUtil;
import com.vividsolutions.jts.geom.Polygon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class MapServiceImpl implements MapService {
    private static final Logger logger = LoggerFactory.getLogger(MapServiceImpl.class);
    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private PoiLocationRepository poiLocationRepository;
    @Autowired
    private PersonnelViewRepository personnelViewRepository;
    @Autowired
    private PersonnelPrisonerViewRepository personnelPrisonerViewRepository;
    @Autowired
    private PersonnelPrisonerRepository personnelPrisonerRepository;
    @Autowired
    private AssetViewRepository assetViewRepository;

    @Override
    public List<PoiLocationEntity> searchLocationInfo(String queryStr) {
        return poiLocationRepository.getTop5ByLocationNameContainingOrderByLocationName(queryStr);
    }

    @Override
    public List<PersonnelView> searchPersonnelInfo(String queryStr) {
        if (RegexUtil.containChinese(queryStr)) {
            return personnelViewRepository.getTop5ByPersonnelNameContainingAndEnabledOrderByPersonnelName(queryStr, 1);
        }
        if (RegexUtil.maybeNameAcronym(queryStr)) {
            return personnelViewRepository.getTop5ByNameAcronymStartingWithAndEnabledOrderByNameAcronym(queryStr, 1);
        }
        if (RegexUtil.isIdNumber(queryStr)) {
            return personnelViewRepository.getByIdNumberAndEnabled(queryStr, 1);
        }
        if (RegexUtil.isPersonnelSn(queryStr)) {
            return personnelViewRepository.getByPersonnelSnAndEnabled(queryStr, 1);
        }
        if (RegexUtil.maybeCardNumber(queryStr)) {
            Long cardNumber = Long.parseLong(queryStr);
            PersonnelView personnelView = personnelViewRepository.getByCardNumber(cardNumber);
            if (personnelView != null) {
                List<PersonnelView> list = new ArrayList<>();
                list.add(personnelView);
                return list;
            }
        }
        if (RegexUtil.isPhoneNumber(queryStr)) {
            return personnelViewRepository.getTop5ByPhoneNumberAndEnabled(queryStr, 1);
        }
        return null;
    }

    @Override
    public List<PersonnelSearchDto> searchPersonnelInfo(String queryStr, Integer prisonerType, Integer locatorAddress) {
        if (prisonerType != null) {
            List<PersonnelPrisonerView> list = null;
            if (locatorAddress != null) {
                switch (prisonerType) {
                    case 150:   //死刑犯
                        list = personnelPrisonerViewRepository.getByIsDeathPrisonerAndEnabledAndLocatorAddress(1, 1, locatorAddress);
                        break;
                    case 151:   //重刑犯
                        list = personnelPrisonerViewRepository.getByIsMajorCriminalOffenderAndEnabledAndLocatorAddress(1, 1, locatorAddress);
                        break;
                    case 152:   //危重病犯
                        list = personnelPrisonerViewRepository.getByIsInfectedPrisonerAndEnabledAndLocatorAddress(1, 1, locatorAddress);
                        break;
                    case 153:   //重点人员
                        list = personnelPrisonerViewRepository.getByIsFocusedPrisonerAndEnabledAndLocatorAddress(1, 1, locatorAddress);
                        break;
                }
            } else {
                switch (prisonerType) {
                    case 150:   //死刑犯
                        list = personnelPrisonerViewRepository.getByIsDeathPrisonerAndEnabled(1, 1);
                        break;
                    case 151:   //重刑犯
                        list = personnelPrisonerViewRepository.getByIsMajorCriminalOffenderAndEnabled(1, 1);
                        break;
                    case 152:   //危重病犯
                        list = personnelPrisonerViewRepository.getByIsInfectedPrisonerAndEnabled(1, 1);
                        break;
                    case 153:   //重点人员
                        list = personnelPrisonerViewRepository.getByIsFocusedPrisonerAndEnabled(1, 1);
                        break;
                }
            }
            if (list != null && list.size() > 0) {
                List<PersonnelSearchDto> dtoList = new ArrayList<>();
                for (PersonnelPrisonerView prisonerView : list) {
                    dtoList.add(new PersonnelSearchDto(prisonerView));
                }
                return dtoList;
            }
        } else {
            if (!StringUtils.isEmpty(queryStr)) {
                List<PersonnelView> list = null;
                do {
                    if (RegexUtil.containChinese(queryStr)) {
                        list = personnelViewRepository.getTop10ByPersonnelNameContainingAndEnabledOrderByPersonnelName(queryStr, 1);
                        break;
                    }else if (RegexUtil.maybeNameAcronym(queryStr)) {
                        list = personnelViewRepository.getTop10ByNameAcronymStartingWithAndEnabledOrderByNameAcronym(queryStr, 1);
                        break;
                    }else if (RegexUtil.isIdNumber(queryStr)) {
                        list = personnelViewRepository.getByIdNumberAndEnabled(queryStr, 1);
                        break;
                    }else if (RegexUtil.isPhoneNumber(queryStr)) {
                        list = personnelViewRepository.getTop10ByPhoneNumberAndEnabled(queryStr, 1);
                        break;
                    }else {
                        String sql = "select * from v_personnel where is_enabled = 1 and (personnel_sn like '%" +queryStr+ "%' or card_number like '%" +queryStr+ "%' or hex_number like '%" +queryStr+ "%')";
                        list = entityManager.createNativeQuery(sql, PersonnelView.class)
                                .getResultList();
                    }


//                    if (RegexUtil.isPersonnelSn(queryStr)) {
//                        list = personnelViewRepository.getByPersonnelSnAndEnabled(queryStr, 1);
//                        break;
//                    }
//                    if (RegexUtil.maybeCardNumber(queryStr)) {
//                        Long cardNumber = Long.parseLong(queryStr);
//                        PersonnelView personnelView = personnelViewRepository.getByCardNumber(cardNumber);
//                        if (personnelView != null) {
//                            list = new ArrayList<>();
//                            list.add(personnelView);
//                            break;
//                        }
//                    }
//                    if(RegexUtil.maybeCardHexNumber(queryStr)){
////                        Long cardNumber  = Long.parseLong(Integer.parseInt(queryStr,16));
//                        PersonnelView personnelView = personnelViewRepository.getByHexNumber(queryStr);
//                        if (personnelView != null) {
//                            list = new ArrayList<>();
//                            list.add(personnelView);
//                            break;
//                        }
//                    }



                } while (false);

                if (list != null && list.size() > 0) {
                    List<PersonnelSearchDto> dtoList = new ArrayList<>();
                    for (PersonnelView personnelView : list) {
                        dtoList.add(new PersonnelSearchDto(personnelView));
                    }
                    setPrisonerProperties(dtoList);
                    return dtoList;
                }
            }
        }
        return null;
    }

    private void setPrisonerProperties(List<PersonnelSearchDto> list) {
        for (PersonnelSearchDto dto : list) {
            if (dto.getPersonnelType().equals(101)) {
                PersonnelPrisonerEntity prisonerEntity = personnelPrisonerRepository.getByPersonnelId(dto.getId());
                if (prisonerEntity != null) {
                    dto.setIsDeathPrisoner(prisonerEntity.getIsDeathPrisoner());
                    dto.setIsMajorCriminalOffender(prisonerEntity.getIsMajorCriminalOffender());
                    dto.setIsInfectedPrisoner(prisonerEntity.getIsInfectedPrisoner());
                    dto.setIsFocusedPrisoner(prisonerEntity.getIsFocusedPrisoner());
                }
            }
        }
    }

    @Override
    public List<PersonnelSearchDto> searchPersonnelInfoInPolygon(Integer prisonerType, Polygon polygon) {
        if (prisonerType != null) {
            String sql = "select * from v_personnel_prisoner v where v.is_enabled = 1 ";
            switch (prisonerType) {
                case 150:   //死刑犯
                    sql += " and v.is_death_prisoner = 1 ";
                    break;
                case 151:   //重刑犯
                    sql += " and v.is_major_criminal_offender = 1 ";
                    break;
                case 152:   //危重病犯
                    sql += " and v.is_infected_prisoner = 1 ";
                    break;
                case 153:   //重点人员
                    sql += " and v.is_focused_prisoner = 1 ";
                    break;
            }
            sql += " and st_contains(:pg, v.pos) ";

            List<PersonnelPrisonerView> list = entityManager.createNativeQuery(sql, PersonnelPrisonerView.class)
                    .setParameter("pg", polygon)
                    .getResultList();

            if (list != null && list.size() > 0) {
                List<PersonnelSearchDto> dtoList = new ArrayList<>();
                for (PersonnelPrisonerView prisonerView : list) {
                    dtoList.add(new PersonnelSearchDto(prisonerView));
                }
                return dtoList;
            }
        }
        return new ArrayList<>();
    }

    @Override
    public PoiLocationEntity getOrgNavigation(Long orgId) {
        return poiLocationRepository.getTopByBindOrgId(orgId);
    }

    @Override
    public List<AssetView> searchAssetInfo(String queryStr, Integer locatorAddress) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        criteria.add(new Criterion("enabled", Criterion.Operator.EQ, Constants.ENABLE_STATUS.ENABLE.id));
        if (!StringUtils.isEmpty(queryStr)) {
            if (RegexUtil.maybeCardNumber(queryStr)) {
                Long cardNumber = Long.parseLong(queryStr);
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, cardNumber));
            } else {
                criteria.add(new Criterion("assetName", Criterion.Operator.LIKE, "%" + queryStr + "%"));
            }
        }
        if (locatorAddress != null) {
            criteria.add(new Criterion("locatorAddress", Criterion.Operator.EQ, locatorAddress));
        }
        List<AssetView> list = assetViewRepository.search(criteria, Sort.by("assetName"));
        return list;
    }

    @Override
    public List<AssetView> searchAssetInfoInPolygon(Polygon polygon) {
        String sql = "select * from v_asset a where a.is_enabled = 1 and st_contains(:pg, a.pos)";
        List<AssetView> list = entityManager.createNativeQuery(sql, AssetView.class)
                .setParameter("pg", polygon)
                .getResultList();
        return list;
    }
}
